﻿using System;
using System.Collections.Specialized;
using System.IO;

namespace Heimdallr
{
    /// <summary>
    /// Represents a notification and its properties and data. this is an abstract class.
    /// </summary> 
    public abstract class Notification
    {
        #region Field

        /// <summary>
        /// Get the default MIME type.
        /// This field is read-only.
        /// </summary>
        public readonly static string DefaultContentType = "application/octet-stream";

        #endregion

        #region Property
         
        /// <summary>
        /// When implemented in a derived class, provides the time of this notification generated.
        /// </summary>
        public abstract DateTime Time
        {
            get;
        }

        /// <summary>
        /// When implemented in a derived class, provides the effective duration of this notification.
        /// </summary>
        /// <remarks>
        /// Providing a negative value means the duration is infinity.
        /// </remarks>
        public abstract TimeSpan Duration
        {
            get;
        }

        /// <summary>
        /// When implemented in a derived class, provides the level of this notification.
        /// </summary>
        /// <remarks>
        /// The default value is <see cref="NotificationLevel">NotificationLevel.Info</see>.
        /// </remarks>
        public abstract NotificationLevel Level
        {
            get;
        }

        /// <summary>
        /// When implemented in a derived class, provides the content type of this notification.
        /// </summary>
        /// <remarks>The value is typically the MIME encoding of the content of this notification.</remarks>
        public abstract string ContentType
        {
            get;
        }

        /// <summary>
        /// When implemented in a derived class, provides the content length of this notification.
        /// </summary>
        public abstract int ContentLength
        {
            get;
        }

        #endregion

        #region Method

        /// <summary>
        /// When implemented in a derived class, creates a read-only stream instance allows user to read the data of notification.
        /// </summary>
        /// <returns>A read-only stream instance.</returns>
        /// <remarks>The property <see cref="Stream.CanWrite"/> of returned value is always false.</remarks>
        public abstract Stream CreateReadOnlyStream();

        /// <summary>
        /// When implemented in a derived class, creates a read-only stream instance with specified buffer size allows user to read the data of notification.
        /// </summary>
        /// <param name="bufferSize">The size of the buffer. This value must be greater than zero.</param>
        /// <returns>A read-only stream instance.</returns>
        /// <exception cref="ArgumentOutOfRangeException">The argument <paramref name="bufferSize"/> is negative or zero.</exception>
        /// <remarks>The property <see cref="Stream.CanWrite"/> of returned value is always false.</remarks>
        public abstract Stream CreateReadOnlyStream(int bufferSize);

        /// <summary>
        /// When implemented in a derived class, writes the notification data to a new byte array and returns it.
        /// </summary>
        /// <returns>A new byte array.</returns>
        /// <exception cref="InvalidOperationException">Can not create buffer.</exception>
        public abstract byte[] GetBuffer();

        #endregion

        #region Others

        /// <summary>
        /// Gets the collection which maps file extensions and MIME types.
        /// </summary>
        /// <returns>The results of mapping file extensions and MIME types.</returns>
        public static NameValueCollection GetDefaultMimeCollection()
        {
            NameValueCollection mimeDic = new NameValueCollection();

            mimeDic.Add(".3gp", "video/3gpp");
            mimeDic.Add(".3g2", "video/3gpp2");
            mimeDic.Add(".asf", "video/x-ms-asf");
            mimeDic.Add(".avi", "video/x-msvideo");
            mimeDic.Add(".bmp", "image/bmp");
            mimeDic.Add(".css", "text/css");
            mimeDic.Add(".csv", "text/csv");
            mimeDic.Add(".flv", "video/x-flv");
            mimeDic.Add(".gif", "image/gif");
            mimeDic.Add(".htm", "text/html");
            mimeDic.Add(".html", "text/html");
            mimeDic.Add(".ico", "image/x-icon");
            mimeDic.Add(".jpeg", "image/jpeg");
            mimeDic.Add(".jpg", "image/jpeg");
            mimeDic.Add(".js", "application/javascript");
            mimeDic.Add(".json", "application/json");
            mimeDic.Add(".log", "text/plain");
            mimeDic.Add(".m3u8", "application/x-mpegURL");
            mimeDic.Add(".mp3", "audio/mpeg");
            mimeDic.Add(".mp4", "video/mp4");
            mimeDic.Add(".pdf", "application/pdf");
            mimeDic.Add(".png", "image/png");
            mimeDic.Add(".rar", "application/x-rar-compressed");
            mimeDic.Add(".swf", "application/x-shockwave-flash");
            mimeDic.Add(".sdp", "application/x-sdp");
            mimeDic.Add(".ts", "video/MP2T");
            mimeDic.Add(".txt", "text/plain");
            mimeDic.Add(".xaml", "application/xaml+xml");
            mimeDic.Add(".xap", "application/x-silverlight-app");
            mimeDic.Add(".xbap", "application/x-ms-xbap");
            mimeDic.Add(".xhtml", "application/xhtml+xml");
            mimeDic.Add(".xml", "application/xml");
            mimeDic.Add(".zip", "application/zip");

            return mimeDic;
        }

        #endregion
    }

    /// <summary>
    /// A set of values designates the level of a <see cref="Notification"/> instance.
    /// </summary>
    public enum NotificationLevel
    {
        /// <summary>
        ///  Designates a notification which represents debugging information.
        /// </summary>
        Debug,

        /// <summary>
        /// Designates a notification which represents regular situation. This is the default value of <see cref="Notification.Level"/> property.
        /// </summary>
        Info,

        /// <summary>
        /// Designates a notification which represents potentially harmful situations.
        /// </summary>
        Warn,

        /// <summary>
        /// Designates a notification which represents one or several errors but might still allow the system to continue running.
        /// </summary>
        Error,

        /// <summary>
        /// Designates very severe error notification.
        /// </summary>
        Fatal,
    }
}